#include <iostream>
#include <map>
#include <set>
#include <vector>
#include "assert.h"

#include "StlVerification.h"

using namespace std;

class CompareFun
{
public:
	bool operator() (const string left, const string right) const
	{
		if(left < right) {
			return true;
		}
		else {
			return false;
		}
	}
};

void StlVerification::mapVerify()
{
	cout<<"-------------------Start map verification---------------------"<<endl;

	cout<<"------------------verify the usage of the default constructor----------------------------"<<endl;
	map<string, int, CompareFun> m;

	cout<<"---------------------------verify the usage of the subscript operator---------------------"<<endl;
	cout<<"m[\"Lily\"]:"<<m["Lily"]<<endl;
	m["Alice"] = 26;
	cout<<"m[\"Alice\"]:"<<m["Alice"]<<endl;
	m["Lily"] = 15;
	cout<<"m[\"Lily\"]:"<<m["Lily"]<<endl;

	cout<<"----------------------------verify the usage of the insert method------------------------"<<endl;
	map<string, int, CompareFun> m2;
	pair<map<string, int, CompareFun>::iterator, bool> ret = m2.insert(map<string, int, CompareFun>::value_type("Jason", 31));
	assert(true == ret.second);
	assert(31 == ret.first->second);
	cout<<"m2[\"Jason\"]"<<m2["Jason"]<<endl;
	ret = m2.insert(make_pair("Tomas", 52));
	assert(true == ret.second);
	assert(52 == ret.first->second);
	cout<<"m2[\"Tomas\"]"<<m2["Tomas"]<<endl;

	map<string, int, CompareFun>::iterator iter_m_b = m.begin();
	map<string, int, CompareFun>::iterator iter_m_e = m.end();
	m2.insert(iter_m_b, iter_m_e);

	ret = m2.insert(make_pair("Alice", 89));
	assert(false == ret.second);
	assert(26 == ret.first->second);

	ret = m2.insert(make_pair("Lily", 43));
	assert(false == ret.second);
	assert(15 == ret.first->second);

	map<string, int, CompareFun>::iterator it_m2 = m2.find("Lason");
	m2.insert(it_m2, make_pair("Jeffery", 28));

	cout<<"-----------------------------verify the usage of the count() method-------------------------"<<endl;
	assert(1 == m2.count("Lily"));
	assert(0 == m2.count("Shawn"));



	cout<<"----------------------------verify the usage of the begin() and end() method----------------"<<endl;
	cout<<"All members of m2:"<<endl;
	map<string, int, CompareFun>::iterator it_m2_traverse = m2.begin();
	for(; it_m2_traverse != m2.end(); ++ it_m2_traverse) {
		cout<<it_m2_traverse->first<<" : "<<it_m2_traverse->second<<endl;
	}

	cout<<"----------------------------verify the usage of the erase() method---------------------------"<<endl;
	map<string, int, CompareFun> m3(m2);
	assert(true == m3.erase("Lily"));
	assert(m3.find("Lily") == m3.end());

	map<string, int, CompareFun>::iterator it_erase = m3.find("Jeffery");
	assert(it_erase != m3.end());
	m3.erase(it_erase);
	assert(m3.find("Jeffery") == m3.end());

	map<string, int, CompareFun>::iterator it_erase_begin = m3.begin();
	map<string, int, CompareFun>::iterator it_erase_end = m3.find("Tomas");
	m3.erase(it_erase_begin, it_erase_end);
	assert(m3.find("Alice") == m3.end());
	assert(m3.count("Alice") == 0);
	assert(m3.find("Jason") == m3.end());
	assert(m3.count("Jason") == 0);
	assert(m3.find("Tomas") != m3.end());
	assert(m3.count("Tomas") == 1);

	cout<<"All members of m3:"<<endl;
	map<string, int, CompareFun>::iterator it_m3 = m3.begin();
	for(; it_m3 != m3.end(); ++ it_m3) {
		cout<<it_m3->first<<" : "<<it_m3->second<<endl;
	}

	map<string, int, CompareFun> m4(m2);
	cout<<"Before erasing, all members of m4:"<<endl;
	map<string, int, CompareFun>::iterator it_m4 = m4.begin();
	for(; it_m4 != m4.end(); ++ it_m4) {
		cout<<it_m4->first<<" : "<<it_m4->second<<endl;
	}
	map<string, int, CompareFun>::iterator it_m4_begin = m4.begin();
	map<string, int, CompareFun>::iterator it_m4_end = m4.end();
	m4.erase(it_m4_begin, it_m4_end);
	cout<<"After erasing, all members of m4:"<<endl;
	it_m4 = m4.begin();
	for(; it_m4 != m4.end(); ++ it_m4) {
		cout<<it_m4->first<<" : "<<it_m4->second<<endl;
	}

	cout<<"----------------------------------------Test OK!---------------------------------------------"<<endl;
}

void StlVerification::setVerify()
{
	cout<<"---------------------start set verification--------------------------"<<endl;

	cout<<"--------------------verify the constructor of set---------------------"<<endl;
	vector<int> v1;
	for(int i = 9; i >= 0; i--) {
		v1.push_back(i);
		v1.push_back(i);
	}
	set<int> s1(v1.begin(), v1.end());

	set<int> s2;

	cout<<"--------------------verify the insert method of set-----------------------"<<endl;
	pair<set<int>::iterator, bool> ret;
	for(vector<int>::iterator it_v1 = v1.begin();
			it_v1 != v1.end(); it_v1 ++) {
		ret = s2.insert(*it_v1);
		if(false == ret.second) {
			cout<<"discard a new node"<<endl;
		}
		else {
			cout<<"insert a new node"<<endl;
		}
	}

	cout<<"-----------------verify traverse of set-----------------------------------"<<endl;
	cout<<"All members of s1"<<endl;
	set<int>::iterator it_s1 = s1.begin();
	for(; it_s1 != s1.end(); it_s1 ++) {
		cout<<*it_s1<<endl;
	}

	cout<<"All members of s2"<<endl;
	set<int>::iterator it_s2 = s2.begin();
	for(; it_s2 != s2.end(); it_s2 ++) {
		cout<<*it_s2<<endl;
	}

	/*------------------------------verify the find() method of set------------------*/
	it_s1 = s1.find(1);
	assert(it_s1 != s1.end());
	it_s1 = s1.find(21);
	assert(it_s1 == s1.end());




	cout<<endl<<"Set Verification test OK!"<<endl;
}

void StlVerification::stringVerify()
{
	/*verify constructor of string*/
	string str1("Hello, world!***", 13);
	cout<<"After construction, str1 is: "<<str1<<endl;

	string str2(str1, 7, 5);
	cout<<"After construction, str2 is: "<<str2<<endl;

	/*verify the length, capacity and max_size op. of string*/
	cout<<"The length of str1 is: "<<str1.length()<<endl;
	cout<<"The capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"The max_size of str1 is:"<<str1.max_size()<<endl;

	/*verify the resize op. of string*/
	str1.resize(18, '$');
	cout<<"After resize, str1 is: "<<str1<<endl;
	cout<<"After resize, the length of str1 is: "<<str1.length()<<endl;
	cout<<"After resize, the capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"After resize, The max_size of str1 is:"<<str1.max_size()<<endl;
	str2.resize(10);
	cout<<"After resize, str2 is: "<<str2<<endl;
	cout<<"After resize, the length of str2 is: "<<str2.length()<<endl;
	cout<<"After resize, the capacity of str2 is: "<<str2.capacity()<<endl;
	cout<<"After resize, The max_size of str2 is:"<<str2.max_size()<<endl;
	const char* str2_c = str2.c_str();
	cout<<"After resize, the C string of str2 is: "<<str2_c<<endl;
	cout<<"The length of C string of str2 is: "<<strlen(str2_c)<<endl;


	cout<<"--------------------------verify the reserve op. of string----------------"<<endl;
	str1.reserve(3);
	cout<<"After reserve, str1 is: "<<str1<<endl;
	cout<<"After reserve, the length of str1 is: "<<str1.length()<<endl;
	cout<<"After reserve, the capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"After reserve, The max_size of str1 is:"<<str1.max_size()<<endl;
	str2.reserve(15);
	cout<<"After reserve, str2 is: "<<str2<<endl;
	cout<<"After reserve, the length of str2 is: "<<str2.length()<<endl;
	cout<<"After reserve, the capacity of str2 is: "<<str2.capacity()<<endl;
	cout<<"After reserve, The max_size of str2 is:"<<str2.max_size()<<endl;

	cout<<"---------------verify the [] op. of string-------------------"<<endl;
	str1[0] = 'A';
	cout<<"After modify the first char, str1 is: "<<str1<<endl;
	const string str1_const(str1);
	cout<<"str1_const[0]: "<<str1_const[0]<<endl;

	cout<<"---------------verify the at op. of string-------------------"<<endl;
	str1.at(0) = 'H';
	cout<<"After modify the first char, str1 is: "<<str1<<endl;
//	str1.at(20) = 'D';

	cout<<"--------------verify the push_back op. of string----------"<<endl;
	str1.push_back('%');
	cout<<"After push_back, str1 is: "<<str1<<endl;
	cout<<"After push_back, the length of str1 is: "<<str1.length()<<endl;
	cout<<"After push_back, the capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"After push_back, The max_size of str1 is:"<<str1.max_size()<<endl;

	cout<<"-----------------verify the assign op. of string---------"<<endl;
	str1.assign("This is a string");
	cout<<"After assign, str1 is: "<<str1<<endl;
	cout<<"After assign, the length of str1 is: "<<str1.length()<<endl;
	cout<<"After assign, the capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"After assign, The max_size of str1 is:"<<str1.max_size()<<endl;

	cout<<"----------------verify the insert op. of string"<<endl;
	string::iterator it;
/*	it = str1.insert(str1.begin() + 5, '@');
	cout<<"*it is: "<<*it<<endl;*/
	str1.insert(str1.begin() + 5, 5, '@');
	cout<<"After insert, str1 is: "<<str1<<endl;
	cout<<"After insert, the length of str1 is: "<<str1.length()<<endl;
	cout<<"After insert, the capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"After insert, The max_size of str1 is:"<<str1.max_size()<<endl;

	cout<<"-----------------Verify the replace op. of string--------------------"<<endl;
	string::iterator it_b = str1.begin();
	str1.replace(it_b+5, it_b+10, 5, '*');
	cout<<"After replace, str1 is: "<<str1<<endl;
	cout<<"After replace, the length of str1 is: "<<str1.length()<<endl;
	cout<<"After replace, the capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"After replace, The max_size of str1 is:"<<str1.max_size()<<endl;

	cout<<"----------------Verify the erase op. of string-------------------"<<endl;
//	str1.erase(it_b+5, it_b+10);
	str1.erase(5, 5);
	cout<<"After erase, str1 is: "<<str1<<endl;
	cout<<"After erase, the length of str1 is: "<<str1.length()<<endl;
	cout<<"After erase, the capacity of str1 is: "<<str1.capacity()<<endl;
	cout<<"After erase, The max_size of str1 is:"<<str1.max_size()<<endl;

	cout<<"------------------Verify the swap op. of string-------------------"<<endl;
	cout<<"Before swap, str1 is: "<<str1<<endl;
	cout<<"Before swap, str2 is: "<<str2<<endl;
	str1.swap(str2);
	cout<<"After swap, str1 is: "<<str1<<endl;
	cout<<"After swap, str2 is: "<<str2<<endl;

	cout<<"------------verify the c_str and data op. of string--------------"<<endl;
	const char* cstr1 = str1.c_str();
	const char* cstr2 = str1.data();
	cout<<"the return data of c_str() is: "<<cstr1<<endl;
	cout<<"the length of cstr1 is: "<<strlen(cstr1)<<endl;
	cout<<"the return data of data() is: "<<cstr2<<endl;
	cout<<"the length of cstr2 is: "<<strlen(cstr2)<<endl;
	str1.at(0) = 'H';
	cout<<"Atfer str1 changed, cstr1 is: "<<cstr1<<endl;

	cout<<"---------------Verify the copy op. of string--------------------"<<endl;
	char cstr_cp[5];
	str2.copy(cstr_cp, 4, 0);
	cout<<"cstr_cp is: "<<cstr_cp<<endl;

//	str2.assign("This i");

	cout<<"str2 is: "<<str2<<endl;

	cout<<"----------------Verify the find op. of string--------------------"<<endl;
	cout<<"The position of the first char i in str2 is: "<<str2.find('i')<<endl;
	cout<<"The position of the first string is in str2 is: "<<str2.find("is", 3)<<endl;

	cout<<"----------------Verify the rfind op. of string--------------------"<<endl;
	cout<<"The position of the last char i in str2 is: "<<str2.rfind('i', 2)<<endl;
	cout<<"The position of the last string is in str2 is: "<<str2.rfind("is", 5)<<endl; //???

	cout<<"----------------Verify the find_first_of op. of string--------------------"<<endl;
	cout<<"The position of the second string is in str2 is: "<<str2.find_first_of("isn", 5)<<endl;

	cout<<"----------------Verify the find_last_of op. of string---------------------"<<endl;
	cout<<"The position of the last string is in str2 is: "<<str2.find_last_of("nis", 2)<<endl;

	cout<<"----------------Verify the substr op. of string----------------------------"<<endl;
	string substr2 = str2.substr(1, 5);
	cout<<"The sub string of str2 is: "<<substr2<<endl;

	cout<<"---------------Verify the compare op. of string--------------------------"<<endl;
	string str3("This is");
	string str4("UAAShis is");
	/*cout<<"The result of comparasion between str3 and str4 is: "
			<<str3.compare(0, str3.length(), str4, 3, str4.length())<<endl;*/
	cout<<"The result of comparasion between str3 and str4 is: "
				<<str3.compare(str4)<<endl;

	cout<<endl<<"-----------------------string Verification test OK!-----------------------"<<endl;
}
